/**
 * User: cjay
 * Date: 22.10.11
 * Time: 13:25
 */
package ru.cjay.loading
{

import core.Facade;

import flash.display.Loader;
import flash.display.LoaderInfo;

import flash.display.Stage;
import flash.events.Event;
import flash.events.EventDispatcher;
import flash.events.IOErrorEvent;
import flash.events.ProgressEvent;
import flash.events.SecurityErrorEvent;
import flash.net.URLLoader;
import flash.net.URLRequest;
import flash.utils.Dictionary;

import ui.IconMessageBox;
import ui.UIEvent;



public class SafeConnection extends EventDispatcher {

    private static var _instance:SafeConnection;
    private static var _allowInstantiation:Boolean;

    private static var window_showed:Boolean = false;

    private static var items:Dictionary = new Dictionary();
    private static var errors:Array = [];

    private static var warningWindow:IconMessageBox;

    public function SafeConnection() {
        if (!_allowInstantiation){
            throw new Error("It is singleton, use 'getInstance()' instead.")
        }
    }

    public static function getInstance():SafeConnection
    {
        if (!_instance){
            _allowInstantiation = true;
            _instance = new SafeConnection();
            _allowInstantiation = false;
        }
     return _instance;
    }

    private function showErrorWindow():void
    {
        if (window_showed) return;
        window_showed = true;
       warningWindow = new IconMessageBox();
        var stage:Stage = Facade.getInstance().stage;

        stage.addChild(warningWindow);
        warningWindow.x = (700-warningWindow.width)*0.5;
        warningWindow.y = (600-warningWindow.height)*0.5;
        warningWindow.alpha = 0;
        warningWindow.scaleZ = 0.5;
        stage.setChildIndex(warningWindow,stage.numChildren-1);
        warningWindow.addEventListener(UIEvent.BUTTON_RETRY,onClickRetry);
        warningWindow.addEventListener(UIEvent.BUTTON_CANCEL,onClickCancel);
        Lerp.getInstance().to(warningWindow,0.5,{alpha:1,scaleZ:1});
    }

    private function hideErrorWindow():void
    {
        warningWindow.removeEventListener(UIEvent.BUTTON_RETRY,onClickRetry);
        warningWindow.removeEventListener(UIEvent.BUTTON_CANCEL,onClickCancel);
        Lerp.getInstance().to(warningWindow,0.5,{alpha:0,scaleX:0.5,scaleY:0.5,handler:function(){
                        window_showed = false;
                        if (warningWindow.parent)
                        {
                            var stage:Stage = Facade.getInstance().stage;
                            stage.removeChild(warningWindow);
                            tryAgain();
                        }
                    }
                    });
    }

    private function tryAgain():void
    {
        if (errors.length==0) return;

        var item:URLLoader;
        var toDelete:Array = [];
        for each (item in errors)
        {
            if (item)
            {
                makeSafe(items[item]["request"],items[item]["handler"],items[item]["progress"],items[item]["format"]);
                toDelete.push(item);
            }
        }
        for each (item in toDelete)
        {
//            items[item] = null;
            delete items[item];
            errors.splice(errors.indexOf(item),1);
        }
        toDelete.length = 0;
    }
    private function onClickRetry(event:Event):void
    {
        hideErrorWindow();
    }
    private function onClickCancel(event:Event):void
    {
        errors.length = 0;
        hideErrorWindow();
    }

    private function onIOError(error:IOErrorEvent):void
    {
        trace("ioError ERROR");
        trace(error.toString());
        errors.push(error.target);
        showErrorWindow();

    }
    private function onSecurityError(error:IOErrorEvent):void
    {
        trace("Secuity ERROR");
        trace(error.toString());
        errors.push(error.target);
        showErrorWindow();


    }

    private function onFinishLoader(event:Event):void
    {
        var loader:LoaderInfo = event.target as LoaderInfo;

        var obj:Object = items[loader];
//        items[loader] = null;
        delete items[loader];
        obj.handler(event);
    }

    private function onFinish(event:Event):void
    {
        var loader:URLLoader = event.target as URLLoader;
        var obj:Object = items[loader];
//        items[loader] = null;
        delete items[loader];
        obj.handler(event);
    }

    public function makeSafeLoader(_request:URLRequest, _handler:Function, _progress:Function=null):void
    {
        var loader:Loader = new Loader();
        loader.contentLoaderInfo.addEventListener(Event.COMPLETE, onFinishLoader);
        loader.contentLoaderInfo.addEventListener(IOErrorEvent.IO_ERROR, onIOError);
        loader.contentLoaderInfo.addEventListener(SecurityErrorEvent.SECURITY_ERROR, onSecurityError);

        if (_progress){
            loader.contentLoaderInfo.addEventListener(ProgressEvent.PROGRESS, _progress);
        }

        var newObj:Object = {request:_request, handler:_handler, progress:_progress, format:null};
        items[loader.contentLoaderInfo]=newObj;
        loader.load(_request);
    }

    public function makeSafe(_request:URLRequest, _handler:Function, _progress:Function=null,_dataFormat:String=null):void
    {
        var loader:URLLoader = new URLLoader();
        loader.addEventListener(Event.COMPLETE, onFinish);
        loader.addEventListener(IOErrorEvent.IO_ERROR, onIOError);
        loader.addEventListener(SecurityErrorEvent.SECURITY_ERROR, onSecurityError);

        if (_dataFormat)
        {
            loader.dataFormat = _dataFormat;
        }

        if (_progress){
            loader.addEventListener(ProgressEvent.PROGRESS, _progress);
        }

        var newObj:Object = {request:_request, handler:_handler, progress:_progress, format:_dataFormat};
        items[loader]=newObj;
        loader.load(_request);
    }

}

}